package com.glsc.ngateway.platform.service.costallocation;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.glsc.ngateway.common.api.common.utils.JsonUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptSearchDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpSearchDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.AppEhrResponse;
import com.glsc.ngateway.common.api.ldap.resp.LdapResponse;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItDict;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItDictData;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItServerDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.it.ItVirtualDevice;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.SystemMain;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.it.ItServerDeviceRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.it.ItVirtualDeviceRepo;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.domain.costallocation.*;
import com.glsc.ngateway.platform.dto.*;
import com.glsc.ngateway.platform.repo.costallocation.*;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.it.DictionaryService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.AssertOverride;
import com.glsc.ngateway.platform.utils.SpecificationUtil;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.glsc.ngateway.platform.utils.report.ReportUploadContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.Collator;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author guoj
 * @description: 数据分摊任务
 * @date 2024/10/17 10:55
 */
@Service
public class CostAllocationTaskService {
    private static Logger logger = LoggerFactory.getLogger(CostAllocationTaskService.class);
    private static final String timeZoneFormatter = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";


    @Value("${defaultSystemNo}")
    private String defaultSystemNo;
    @Resource
    private IFeignLdapService iFeignLdapService;
    @Autowired
    private ItVirtualDeviceRepo itVirtualDeviceRepo;

    //临时放置  Constant编译十分钟
    @Autowired
    private ItServerDeviceRepo itServerDeviceRepo;
    @Autowired
    private UserCache userCache;
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private CostAllocationTaskRepo costAllocationTaskRepo;
    @Autowired
    private HisDepCostAllocationRepo hisDepCostAllocationRepo;

    @Resource
    private SystemMainService systemMainService;
    @Resource
    IFeignLdapService feignLdapService;
    @Autowired
    private HisIpInfoRepo hisIpInfoRepo;
    @Autowired
    private HisIpDetailInfoRepo hisIpDetailInfoRepo;
    @Autowired
    private HisBusiSystemInfoRepo hisBusiSystemInfoRepo;
    @Autowired
    private IpInfoRepo ipInfoRepo;
    @Autowired
    private IpDetailInfoRepo ipDetailInfoRepo;
    @Autowired
    private BusiSystemInfoRepo busiSystemInfoRepo;
    @Autowired
    private DepCostAllocationRepo depCostAllocationRepo;
    @Autowired
    private ReplenishmentInfoRepo replenishmentInfoRepo;
    @Resource
    private UserService userService;
    @Autowired
    private DictionaryService dictionaryService;

    public Page<CostAllocationTask> findPage(CostAllocationTaskQueryDto queryDto) {
        logger.info("开始查询数据分摊信息：{}", queryDto.toString());
        boolean allNull = StrUtil.isBlank(queryDto.getTaskName())
                && StrUtil.isBlank(queryDto.getSystemClassNo())
                && StrUtil.isBlank(queryDto.getDepGradeOneId())
                && StrUtil.isBlank(queryDto.getStartDate())
                && StrUtil.isBlank(queryDto.getEndDate());
        if(allNull){
            return Page.empty();
        }
        String pageSizeQuery = queryDto.getPageSize();
        String pageNoQuery = queryDto.getPageNo();
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "id";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        String queryDtoSystemClassNo = queryDto.getSystemClassNo();
        if(StrUtil.isNotEmpty(queryDtoSystemClassNo)){
            param.put("EQ_systemClassNo",queryDtoSystemClassNo);
        }

        String taskName = queryDto.getTaskName();
        if (StrUtil.isNotEmpty(taskName)) {
            param.put("LIKE_taskName", taskName);
        }

        String ip = queryDto.getVcIp();
        if (StrUtil.isNotEmpty(ip)) {
            param.put("LIKE_vcIp", ip);
        }

        String dataSource = queryDto.getDataSource();
        if (StrUtil.isNotEmpty(dataSource)) {
            param.put("EQ_dataSource", dataSource);
        }

        String depGradeOneId = queryDto.getDepGradeOneId();
        if (StrUtil.isNotEmpty(depGradeOneId)) {
            param.put("EQ_depGradeOneId", depGradeOneId);
        }
        String startDate = queryDto.getStartDate();
        if(StringUtils.isNotBlank(startDate)){
            param.put("GTE_startDate", startDate);
        }
        String endDate = queryDto.getEndDate();
        if(StringUtils.isNotBlank(endDate)){
            param.put("LTE_endDate", endDate);
        }
        List<CostAllocationTask> all = costAllocationTaskRepo.findAll(SpecificationUtil.buildSpecification(param, CostAllocationTask.class));
        Page<CostAllocationTask> result = Page.empty();
        if(CollectionUtil.isNotEmpty(all)){
            List<SystemMain> systemMainList = systemMainService.queryAll();
            Map<String,String> systemNameMap = systemMainList.stream().collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));
            LdapResponse<List<LdapEhrDeptDto>> deptList = iFeignLdapService.getDepartmentList(new LdapEhrDeptSearchDto());
            Map<Integer,String> deptNameMap = deptList.getData().stream()
                    .filter(x-> "一级部门".equals(x.getDepgrade()))
                    .peek(e-> e.setDtitle(e.getDtitle().trim())).collect(Collectors.toMap(LdapEhrDeptDto::getDepid, x->{
                String dtitle = x.getDtitle();
                String comptitle = x.getComptitle();
                if(StrUtil.isNotBlank(dtitle)
                        && StrUtil.isNotBlank(comptitle)
                        && !dtitle.startsWith(comptitle)){
                    dtitle =comptitle +"/" +dtitle;
                }
                return dtitle;
            }));
            for (CostAllocationTask temp : all) {
                temp.setSystemName(systemNameMap.get(temp.getSystemClassNo()));

                String depGradeOneId1 = temp.getDepGradeOneId();
                if (!StringUtils.isBlank(depGradeOneId1)) {
                    temp.setDepGradeOneName(deptNameMap.get(Integer.valueOf(depGradeOneId1)));
                }
            }
            result = PageUtil.listConvertToPage(all, pageable);
        }
        return result;
    }

    /**
     * 生成数据分摊任务
     *
     * @param costAllocationTaskQueryDto
     */
    public void genCostAllocationTask(CostAllocationTaskQueryDto costAllocationTaskQueryDto) {

        logger.info("开始查询数据分摊信息：{}", costAllocationTaskQueryDto.toString());
        checkParam(costAllocationTaskQueryDto);
        String startDate = costAllocationTaskQueryDto.getStartDate();
        String endDate = costAllocationTaskQueryDto.getEndDate();
        String taskName = costAllocationTaskQueryDto.getTaskName();
        PlatformUserDto user = userCache.get(request);
        String currUserOA = user.getUsername();
        List<HisIpDetailInfo> detailInfos = hisIpDetailInfoRepo.findAll();
        Map<Long, List<HisIpDetailInfo>> hisIpinfoId2List = detailInfos.stream()
                //过滤默认系统 前提默认系统只有一个分摊比例
                // 34-0-015 测试环境 34-0-032 生产
                .filter(x -> !Objects.equals(defaultSystemNo,x.getSystemClassNo()))
                .collect(Collectors.groupingBy(HisIpDetailInfo::getIpInfoId));

        List<HisIpInfo> all = hisIpInfoRepo.findAll();
        Map<String, List<HisIpInfo>> uniquekey2List = all.stream()
                //应用详情没有分摊数据 且应用详情流水【原因：分摊比例可能先有后无】也无分摊数据
                .filter(x -> hisIpinfoId2List.containsKey(x .getId()))
                .collect(Collectors.groupingBy(HisIpInfo::getUniqueKey));
        //准备全部数据  唯一标识： 正序列表
        Map<String, List<HisIpInfo>> initData = prepareData(uniquekey2List,startDate,endDate);
        //按照ip的分摊比例操作流水 分片
        List<CostAllocationDateSeg> firstSeg = genFirstSeg(detailInfos,initData, endDate);
        //按照系统的分摊比例操作流水 分片
        List<CostAllocationTask> toSaveList = genSecondSeg(currUserOA,firstSeg,taskName,startDate,endDate);
        //处理默认系统
        List<CostAllocationTask> afterDefaultSystem = specialDefaultSystem(taskName,toSaveList,startDate,endDate,currUserOA);
        costAllocationTaskRepo.saveAll(afterDefaultSystem);
    }

    /**
     * 默认系统 全部分摊的责任人所在部门
     * @param taskName
     * @param toSaveList
     * @param startDate
     * @param endDate
     * @param currUserOA
     * @return
     */
    private List<CostAllocationTask> specialDefaultSystem(String taskName,List<CostAllocationTask> toSaveList,
                                                          String startDate,String endDate,String currUserOA) {
        List<HisIpDetailInfo> detailInfos = hisIpDetailInfoRepo.queryBysystemClassNo(defaultSystemNo);
        if(CollectionUtil.isEmpty(detailInfos)){
            return toSaveList;
        }
        Set<Long> ids = detailInfos.stream()
                .map(HisIpDetailInfo::getIpInfoId)
                .collect(Collectors.toSet());
        List<HisIpInfo> hisIpInfos = hisIpInfoRepo.queryByids(ids);
        List<HisIpInfo> filterByCreaeDate = hisIpInfos.stream().filter(x -> {
            String createDate = x.getCreateTime().toLocalDate().toString();
            return createDate.compareTo(startDate) >= 0
                    && createDate.compareTo(endDate) <= 0;
        }).collect(Collectors.toList());
        Map<String, List<HisIpInfo>> unikey2List = filterByCreaeDate.stream()
                .collect(Collectors.groupingBy(HisIpInfo::getUniqueKey));
        Map<String, List<HisIpInfo>> unikey2ListMap = prepareData(unikey2List, startDate, endDate);
        List<CostAllocationDateSeg> costAllocationDateSegs = genFirstSeg(detailInfos, unikey2ListMap, endDate);

        Set<String> virtualIds = hisIpInfos.stream()
                .map(HisIpInfo::getUniqueKey)
                .filter(uniqueKey -> uniqueKey.startsWith("VD"))
                .collect(Collectors.toSet());
        List<ItVirtualDevice> itVirtualDevices = itVirtualDeviceRepo.queryByIds(virtualIds);
        Map<String, String> uniqueVD2Ip1 = itVirtualDevices.stream()
                .collect(Collectors.toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getIp1));

        Set<Integer> sdIds = hisIpInfos.stream()
                .map(HisIpInfo::getUniqueKey)
                .filter(uniqueKey -> !uniqueKey.startsWith("VD"))
                .map(Integer::parseInt)
                .collect(Collectors.toSet());
        List<ItServerDevice> itServerDevices = itServerDeviceRepo.queryByIds(sdIds);


        Map<String, String> uniqueSD2IP = itServerDevices.stream()
                .collect(Collectors.toMap(x-> x.getDevId().toString(), ItServerDevice::getIp1));
        BigDecimal oneHundred = new BigDecimal("100");
        Map<String, Integer> userOaId2Depid = userOAID2DepGradeOne();
        for(CostAllocationDateSeg item : costAllocationDateSegs){
            String uniqueKey = item.getUniqueKey();
            Integer gradeOneDepId = userOaId2Depid.get(item.getSystemUserId());

            String ipTemp = uniqueVD2Ip1.get(uniqueKey);
            String ip = StrUtil.isNotBlank(ipTemp) ? ipTemp : uniqueSD2IP.get(uniqueKey);
            CostAllocationTask toSave = new CostAllocationTask();
            toSave.setSystemClassNo(defaultSystemNo);
            toSave.setSectionStartDate(item.getStartDate());
            toSave.setSectionEndDate(item.getEndDate());
            toSave.setItUniqueKey(uniqueKey);
            toSave.setVcIp(ip);
            toSave.setCreateTime(LocalDateTime.now());
            toSave.setDepGradeOneId(String.valueOf(gradeOneDepId));
            toSave.setDepAllocation(oneHundred);
            toSave.setSystemAllocation(oneHundred);
            toSave.setTaskName(taskName);
            toSave.setEndDate(endDate);
            toSave.setDataSource("01");
            toSave.setStartDate(startDate);
            toSave.setVcComponentName(item.getComponentName());
            toSave.setOperator(currUserOA);
            toSaveList.add(toSave);
        }
        return toSaveList;
    }

    /**
     * useroaid 和 一级部门的映射
     * @return
     */
    public Map<String, Integer> userOAID2DepGradeOne(){
        LdapResponse<List<LdapEhrEmpDto>> ehrList = iFeignLdapService.getUserList(new LdapEhrEmpSearchDto());
        List<LdapEhrEmpDto> data = ehrList.getData();
        Map<String,LdapEhrEmpDto> ehrMap = data.stream()
                .collect(Collectors.toMap(LdapEhrEmpDto::getBadge, Function.identity(), (key1, key2) -> key2));
        //二级部门的一级部门id
        Map<Integer, Integer> deptwo2depone = new HashMap<>();
        List<LdapEhrEmpDto> collect = data.stream().filter(x -> {
            LdapEhrDeptDto deptinfo = x.getDeptinfo();
            return Objects.nonNull(x.getDepid()) &&
                    (Objects.isNull(deptinfo) || "二级部门".equals(deptinfo.getDepgrade()));
        }).collect(Collectors.toList());
        for(LdapEhrEmpDto item : collect){
            Integer depid = item.getDepid();
            if(!deptwo2depone.keySet().contains(depid)){
                LdapEhrDeptDto deptinfo = item.getDeptinfo();
                deptwo2depone.put(depid,Objects.isNull(deptinfo)? depid : deptinfo.getSuperDeptId());
            }
        }
        Map<String, Integer> userOaId2Depid = new HashMap<>();
        for (String oaName : ehrMap.keySet()) {
            LdapEhrEmpDto ldapEhrEmpDto = ehrMap.get(oaName);
            LdapEhrDeptDto deptinfo = ldapEhrEmpDto.getDeptinfo();
            if(Objects.isNull(deptinfo)){
                userOaId2Depid.put(oaName,ldapEhrEmpDto.getDepid());
            }else{
                String depgrade = deptinfo.getDepgrade();
                Integer depTwotId = deptinfo.getSuperDeptId();
                if("一级部门".equals(depgrade)){
                    userOaId2Depid.put(oaName,ldapEhrEmpDto.getDepid());
                }else if("二级部门".equals(depgrade)){
                    userOaId2Depid.put(oaName, depTwotId);
                }else{//三级部门
                    userOaId2Depid.put(oaName, deptwo2depone.get(depTwotId));
                }
            }
        }
        return userOaId2Depid;
    }

    /**
     * 保存待导出任务
     * @param firstSeg
     * @param taskName
     * @param startDateOut
     * @param endDateOut
     */
    public List<CostAllocationTask>  genSecondSeg(String currUserOA,List<CostAllocationDateSeg> firstSeg,String taskName,String startDateOut,String endDateOut){
        List<HisBusiSystemInfo> all = hisBusiSystemInfoRepo.findAll();
        List<HisDepCostAllocation> hisDepCostAllocationList = hisDepCostAllocationRepo.findAll();
        Set<Long> allBusiIDFromDetail = hisDepCostAllocationList.stream()
                .map(HisDepCostAllocation::getSystemInfoId)
                .collect(Collectors.toSet());
        Map<Long, List<HisDepCostAllocation>> systemInfoId2List = hisDepCostAllocationList.stream()
                .collect(Collectors.groupingBy(HisDepCostAllocation::getSystemInfoId));
        Map<String, List<HisBusiSystemInfo>> systemNo2List = all.stream()
                .filter(x ->{
                    boolean contains = allBusiIDFromDetail.contains(x.getId());
                    boolean blank = StrUtil.isBlank(x.getSpecilaDep());
                    //编辑分摊 和勾选分摊有且只能有一种方式
                    return  (contains && blank) || (!contains && !blank);
                })
                .collect(Collectors.groupingBy(HisBusiSystemInfo::getSystemClassNo));
        Map<String, List<HisBusiSystemInfo>> systemNo2ListASC = new HashMap<>();
        Map<Integer, Long> depId2Count = getDepId2Count();
        for (String systemNo : systemNo2List.keySet()) {
            List<HisBusiSystemInfo> hisBusiSystemInfos = systemNo2List.get(systemNo);
            List<HisBusiSystemInfo> afterMegerOneDay = mergeSystemInfoAtOneDay(hisBusiSystemInfos);
            handleSpecialMode(depId2Count,afterMegerOneDay,systemInfoId2List);
            List<HisBusiSystemInfo> orderedASC = afterMegerOneDay
                    .stream()
                    .sorted(new Comparator<HisBusiSystemInfo>() {
                @Override
                public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            }).collect(Collectors.toList());
            systemNo2ListASC.put(systemNo,orderedASC);
        }
        List<CostAllocationTask> toSaveList = new ArrayList<>();
        for(CostAllocationDateSeg item : firstSeg){
            String systemClassNo = item.getSystemClassNo();
            String uniqueKey = item.getUniqueKey();
            String componentName = item.getComponentName();
            String ip = item.getIp();
            String startDate = item.getStartDate();
            String endDate = item.getEndDate();
            BigDecimal systemAllocation = item.getSystemAllocation();

            List<HisBusiSystemInfo> hisBusiSystemInfos = systemNo2ListASC.getOrDefault(systemClassNo,new ArrayList<>());
            List<HisBusiSystemInfo> betweenList = hisBusiSystemInfos.stream()
                    .filter(x -> {
                                String currentDate = x.getCreateTime().toLocalDate().toString();
                                return startDate.compareTo(currentDate) <= 0
                                        && endDate.compareTo(currentDate) > 0;
                            }
                    ).collect(Collectors.toList());
            List<HisBusiSystemInfo> afterAddFirstOne = addFirstHisSystemInfo(startDate,betweenList,hisBusiSystemInfos);
            afterAddFirstOne.sort(new Comparator<HisBusiSystemInfo>() {
                @Override
                public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            int size = afterAddFirstOne.size();
            int lastSection = size - 1;
            for (int i = 0; i < size; i++) {
                HisBusiSystemInfo temp = afterAddFirstOne.get(i);
                String firstSegStartDate = temp.getCreateTime().toLocalDate().toString();
                //二级分段 区间终止时间 最后一段取终点
                // 其他分段取当前循环节点的下一个
                String firstSegEndDate = endDate;
                if (i != lastSection) {
                    firstSegEndDate = afterAddFirstOne.get(i + 1).getCreateTime().toLocalDate().toString();
                }
                Long id = temp.getId();
                List<HisDepCostAllocation> hisList = systemInfoId2List.get(id);
                for(HisDepCostAllocation hisItem : hisList){
                    CostAllocationTask toSave = new CostAllocationTask();
                    toSave.setSystemClassNo(systemClassNo);
                    toSave.setSectionStartDate(firstSegStartDate);
                    toSave.setSectionEndDate(firstSegEndDate);
                    toSave.setItUniqueKey(uniqueKey);
                    toSave.setVcIp(ip);
                    toSave.setVcComponentName(componentName);
                    toSave.setCreateTime(LocalDateTime.now());
                    toSave.setDepGradeOneId(hisItem.getDepGradeOneId());
                    toSave.setDepAllocation(hisItem.getCostAllocation());
                    toSave.setSystemAllocation(systemAllocation);
                    toSave.setTaskName(taskName);
                    toSave.setDataSource("01");
                    toSave.setEndDate(endDateOut);
                    toSave.setStartDate(startDateOut);
                    toSave.setOperator(currUserOA);
                    toSaveList.add(toSave);
                }
            }
        }
        logger.info("数据分摊-第二次分片数据大小：{}，内容：{}", toSaveList.size(),toSaveList);
        return toSaveList;
    }

    //部门id:部门人数
    public Map<Integer, Long>  getDepId2Count(){
        List<LdapEhrDeptDto> allDept = iFeignLdapService.getAllDept().getData();
        Set<Integer> allDepGradeOne = allDept.stream()
                .filter(x -> Objects.equals("一级部门", x.getDepgrade()))
                .map(LdapEhrDeptDto::getDepid)
                .collect(Collectors.toSet());

        List<LdapEhrEmpDto> allEmps = iFeignLdapService.getAllEmps().getData();
        return allEmps.stream().filter(x -> allDepGradeOne.contains(x.getDepid()))
                .collect(Collectors.groupingBy(LdapEhrEmpDto::getDepid, Collectors.counting()));
    }

    /**
     * 处理系统信息中全部门分摊的勾选方式的分摊
     * 根据勾选结果，临时生成一组分摊比例数据，
     * 添加到分摊数据里
     * @param dep2Size 部门id:部门人数
     * @param afterMegerOneDay 编辑分摊 + 勾选分摊的数据
     * @param systemInfoId2List 只有编辑分摊的比例
     */
    public void handleSpecialMode(Map<Integer, Long> dep2Size,List<HisBusiSystemInfo> afterMegerOneDay,
                                  Map<Long, List<HisDepCostAllocation>> systemInfoId2List){
        List<HisBusiSystemInfo> isSpecial = afterMegerOneDay.stream()
                .filter(x -> StringUtils.isNotBlank(x.getSpecilaDep()))
                .collect(Collectors.toList());
        BigDecimal bd100 = new BigDecimal("100");
        for(HisBusiSystemInfo item : isSpecial) {
            Long hisSystemID = item.getId();
            JSONArray jsonArray = JSON.parseArray(item.getSpecilaDep());
            List<AllDepDto> allDepDtos = jsonArray.toJavaList(AllDepDto.class);
            //选中的一级部门id列表
            Set<Integer> gradeOneIds = allDepDtos.stream()
                    .filter(x -> x.getKey().contains("#"))
                    .map(x -> {
                        String key = x.getKey();
                        return Integer.valueOf(key.substring(key.indexOf("#") + 1));
                    }).collect(Collectors.toSet());
            Long count = 0L;
            for(Integer i : gradeOneIds){
                Long orDefault = dep2Size.getOrDefault(i, 0L);
                count = count + orDefault;
            }
            //说明之前选中的部门被取消
            if(count.compareTo(0L) ==0){
                continue;
            }
            BigDecimal totalCurr = new BigDecimal(count);
            List<HisDepCostAllocation> add2List = new ArrayList();
            for(Integer i : gradeOneIds){
                Long orDefault = dep2Size.getOrDefault(i, 0L);
                if (orDefault.compareTo(0L) == 0) {
                    continue;
                }
                BigDecimal temp = new BigDecimal(orDefault);
                HisDepCostAllocation hisDepCostAllocation = new HisDepCostAllocation();
                hisDepCostAllocation.setSystemInfoId(hisSystemID);
                hisDepCostAllocation.setDepGradeOneId(i.toString());
                BigDecimal divide = temp.divide(totalCurr, 6, RoundingMode.HALF_UP).multiply(bd100);
                hisDepCostAllocation.setCostAllocation(divide);
                add2List.add(hisDepCostAllocation);
            }
            systemInfoId2List.put(hisSystemID,add2List);
        }
    }

    /**
     * 合并一天 如果同一个系统 一天有多次分摊比例 取当天最后一次操作记录 其他移除
     * @param hisBusiSystemInfos 同一个系统
     * @return
     */
    private List<HisBusiSystemInfo> mergeSystemInfoAtOneDay(List<HisBusiSystemInfo> hisBusiSystemInfos){
        if (CollectionUtil.isEmpty(hisBusiSystemInfos)) {
            return hisBusiSystemInfos;
        }
        Map<String, List<HisBusiSystemInfo>> date2List = hisBusiSystemInfos.stream()
                .filter(x -> Objects.nonNull(x.getCreateTime()))
                .collect(Collectors.groupingBy(x -> x.getCreateTime().toLocalDate().toString()));
        List<HisBusiSystemInfo> resutl = new ArrayList<>();
        for (String date : date2List.keySet()) {
            HisBusiSystemInfo temp = new HisBusiSystemInfo();
            List<HisBusiSystemInfo> hisBusiSystemInfos1 = date2List.get(date);
            //同一日期只有一个分摊比例
            if (hisBusiSystemInfos1.size() == 1) {
                temp = hisBusiSystemInfos1.get(0);
            }else{ //同一日期有多次分摊比例 只取最后一个操作
                hisBusiSystemInfos1.sort(new Comparator<HisBusiSystemInfo>() {
                    @Override
                    public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                        return o1.getCreateTime().compareTo(o2.getCreateTime());
                    }
                });
                temp = hisBusiSystemInfos1.get(hisBusiSystemInfos1.size() - 1);
            }
            resutl.add(temp);
        }
        return resutl;

    }

    /**
     * 补充开始时间点的数据
     * @param startDate
     * @param hisBusiSystemInfos
     * @return
     */
    public List<HisBusiSystemInfo> addFirstHisSystemInfo(String startDate,List<HisBusiSystemInfo> betweenList,List<HisBusiSystemInfo> hisBusiSystemInfos){
        if (CollectionUtil.isEmpty(hisBusiSystemInfos)) {
            return  hisBusiSystemInfos;
        }
        //开始日期有值 直接添加后返回
        Optional<HisBusiSystemInfo> first = betweenList.stream()
                .filter(x -> startDate.equals(x.getCreateTime().toLocalDate().toString()))
                .findFirst();
        if (first.isPresent()) {
            //起始日期当天有值 则不必添加
            //systemNo2ListASC.add(0,first.get()) ;
            return betweenList;
        }

        List<HisBusiSystemInfo> allLeft = hisBusiSystemInfos.stream()
                .filter(x -> startDate.compareTo(x.getCreateTime().toLocalDate().toString()) > 0)
                .collect(Collectors.toList());
        HisBusiSystemInfo left = new HisBusiSystemInfo();
        if (CollectionUtil.isNotEmpty(allLeft)) {
            allLeft.sort(new Comparator<HisBusiSystemInfo>() {
                @Override
                public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            BeanUtils.copyProperties( allLeft.get(allLeft.size() - 1),left);
        }

        List<HisBusiSystemInfo> allRight = hisBusiSystemInfos.stream()
                .filter(x -> startDate.compareTo(x.getCreateTime().toLocalDate().toString()) < 0)
                .collect(Collectors.toList());
        HisBusiSystemInfo right = new HisBusiSystemInfo();
        if (CollectionUtil.isNotEmpty(allRight)) {
            allLeft.sort(new Comparator<HisBusiSystemInfo>() {
                @Override
                public int compare(HisBusiSystemInfo o1, HisBusiSystemInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            BeanUtils.copyProperties(allRight.get(0),right);
        }
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime newCreatTime = LocalDateTime.of(LocalDate.parse(startDate, dateFormatter), LocalTime.MIDNIGHT);
        // 前面逻辑保证left riht不会同时为空
        // 优先取左侧数据填充
        if (Objects.isNull(left.getId())) {
            right.setCreateTime(newCreatTime);
            betweenList.add(0, right);
        } else {
            left.setCreateTime(newCreatTime);
            betweenList.add(0, left);
        }
        return betweenList;
    }

    /**
     * 按照IP的分摊比例操作流水 将同一个ip的记录拆分为对应多个时间段
     *  a---b---c--d 四个记录 则生成三个dto，其比例值分别对应 a、b、c
     * @param initData
     * @param endDate
     * @return
     */
    public  List<CostAllocationDateSeg> genFirstSeg(List<HisIpDetailInfo> allDetail,Map<String, List<HisIpInfo>> initData,String endDate){
        Map<Long, List<HisIpDetailInfo>> infoId2List = allDetail.stream()
                .collect(Collectors.groupingBy(HisIpDetailInfo::getIpInfoId));
        List<CostAllocationDateSeg> ipSeg = new ArrayList<>();
        for (String uniquekey : initData.keySet()) {
            List<HisIpInfo> hisIpInfos = initData.get(uniquekey);
            int size = hisIpInfos.size();
            int lastSection = size - 1;
            for (int i = 0; i < size; i++) {
                HisIpInfo hisIpInfo = hisIpInfos.get(i);
                String ip = hisIpInfo.getIp();
                String systemUserId = hisIpInfo.getSystemUserId();
                //一级分段 区间起始时间
                String firstSegStartDate = hisIpInfo.getCreateTime().toLocalDate().toString();
                Long id = hisIpInfo.getId();
                //一级分段 区间终止时间 最后一段取终点
                // 其他分段取当前循环节点的下一个
                String firstSegEndDate = endDate;
                if (i != lastSection) {
                    firstSegEndDate = hisIpInfos.get(i + 1).getCreateTime().toLocalDate().toString();
                }
                List<HisIpDetailInfo> detailInfos = infoId2List.get(id);
                //合并相同系统
                //List<HisIpDetailInfo> afterMerge = mergeSameSystem(detailInfos);
                for(HisIpDetailInfo hisIpDetailInfo : detailInfos){
                    CostAllocationDateSeg costAllocationDateSeg = new CostAllocationDateSeg();
                    costAllocationDateSeg.setStartDate(firstSegStartDate);
                    costAllocationDateSeg.setIp(ip);
                    costAllocationDateSeg.setSystemUserId(systemUserId);
                    costAllocationDateSeg.setComponentName(hisIpDetailInfo.getComponentName());
                    costAllocationDateSeg.setEndDate(firstSegEndDate);
                    costAllocationDateSeg.setSystemAllocation(hisIpDetailInfo.getSourceAllocation());
                    costAllocationDateSeg.setSystemClassNo(hisIpDetailInfo.getSystemClassNo());
                    costAllocationDateSeg.setUniqueKey(uniquekey);
                    ipSeg.add(costAllocationDateSeg);
                }
            }
        }
        logger.info("数据分摊-第一次数据大小：{}，内容：{}", ipSeg.size(),ipSeg);
        return ipSeg;
    }

    /**
     * 将同一个ip的分摊比例中 相同系统的分摊比例合并在一起
     * @param detailInfos
     * @return
     */
    public List<HisIpDetailInfo> mergeSameSystem(List<HisIpDetailInfo> detailInfos){
        if(CollectionUtil.isEmpty(detailInfos)){
            return detailInfos;
        }
        Map<String, List<HisIpDetailInfo>> systemNo2List = detailInfos.stream()
                .collect(Collectors.groupingBy(HisIpDetailInfo::getSystemClassNo));
        List<HisIpDetailInfo> result = new ArrayList<>();
        for (String systemNo : systemNo2List.keySet()) {
            List<HisIpDetailInfo> detailInfosTemp = systemNo2List.get(systemNo);
            HisIpDetailInfo e = detailInfosTemp.get(0);
            if(detailInfosTemp.size() > 1){
                //多个时候 合并分摊比例
                BigDecimal reduce = detailInfosTemp.stream()
                        .map(HisIpDetailInfo::getSourceAllocation)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                e.setSourceAllocation(reduce);
            }
            result.add(e);
        }
        return result;
    }

    /**
     * 过滤应用详情流水，过滤以下
     * 1、应用详情没有分摊数据 且应用详情流水【原因：分摊比例可能先有后无】也无分摊数据
     * 2、首次分摊比例数据在目标区间右侧（包含）以外
     * 3、最后一次分摊数据【下架删除】在左侧（包含）以外的
     * 4、一天分摊多次的 按当天最后一次分摊为准。
     * @param startDate
     * @param endDate
     */
    public Map<String, List<HisIpInfo>> prepareData(Map<String, List<HisIpInfo>> uniquekey2List,String startDate,String endDate){
        Map<String, List<HisIpInfo>> afterFilter = new HashMap<>();
        for (String uniquekey : uniquekey2List.keySet()) {
            List<HisIpInfo> hisIpInfosTemp = uniquekey2List.get(uniquekey);
            //创建时间正序
            hisIpInfosTemp.sort(new Comparator<HisIpInfo>() {
                @Override
                public int compare(HisIpInfo o1, HisIpInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            HisIpInfo first = hisIpInfosTemp.get(0);
            String  firstChangeDay = first.getCreateTime()
                    .toLocalDate().toString();
            //2、首次分摊比例数据在目标区间右侧（包含）以外
            if(endDate.compareTo(firstChangeDay) <= 0){
                continue;
            }
            HisIpInfo last = hisIpInfosTemp.get(hisIpInfosTemp.size() - 1);
            if("03".equals(last.getChangeType())){
                String  lastChangeDay = last.getCreateTime()
                        .toLocalDate().toString();
                //3、最后一次分摊数据【下架删除】在左侧（包含）以外的
                if (startDate.compareTo(lastChangeDay) >= 0) {
                    continue;
                }
            }
            //4、一天分摊多次的 按当天最后一次分摊为准。
            List<HisIpInfo> hisIpInfos = lastRecordsAtOneDay(hisIpInfosTemp);
            if(CollectionUtil.isNotEmpty(hisIpInfos)){
                //筛选出区间数据
                List<HisIpInfo> betweenStartAndEnd = hisIpInfos.stream().filter(x -> {
                    String changeDate = x.getCreateTime().toLocalDate().toString();
                    return startDate.compareTo(changeDate) <= 0 && endDate.compareTo(changeDate) > 0;
                }).collect(Collectors.toList());
                //补充第一个节点
                hisIpInfos = addStartDateData(startDate,hisIpInfos,betweenStartAndEnd);
                hisIpInfos.sort(new Comparator<HisIpInfo>() {
                    @Override
                    public int compare(HisIpInfo o1, HisIpInfo o2) {
                        return o1.getCreateTime().compareTo(o2.getCreateTime());
                    }
                });
                afterFilter.put(uniquekey,hisIpInfos);
            }
        }
        logger.info("数据分摊-初始化数据大小：{}，内容：{}", afterFilter.size(),JsonUtil.Obj2Str(afterFilter));
        return afterFilter;
    }

    /**
     * 补充起始节点的分摊数据 将其作为第一个区间的分摊比例
     * @param startDate
     * @param hisIpInfos
     * @return
     */
    public List<HisIpInfo>  addStartDateData(String startDate,List<HisIpInfo> hisIpInfos,List<HisIpInfo> betweenStartAndEnd){
        if (CollectionUtil.isEmpty(hisIpInfos)) {
            return  hisIpInfos;
        }
        //开始日期有值 直接添加后返回
        Optional<HisIpInfo> first = betweenStartAndEnd.stream().filter(x ->
                startDate.equals(x.getCreateTime().toLocalDate().toString())).findFirst();
        if (first.isPresent()) {
            //hisIpInfos.add(0,first.get()) ;
            return hisIpInfos;
        }

        List<HisIpInfo> allLeft = hisIpInfos.stream()
                .filter(x -> startDate.compareTo(x.getCreateTime().toLocalDate().toString()) > 0)
                .collect(Collectors.toList());
        HisIpInfo left = new HisIpInfo();
        if (CollectionUtil.isNotEmpty(allLeft)) {
            allLeft.sort(new Comparator<HisIpInfo>() {
                @Override
                public int compare(HisIpInfo o1, HisIpInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            BeanUtils.copyProperties(allLeft.get(allLeft.size() - 1),left);
        }

        List<HisIpInfo> allRight = hisIpInfos.stream()
                .filter(x -> startDate.compareTo(x.getCreateTime().toLocalDate().toString()) < 0)
                .collect(Collectors.toList());
        HisIpInfo right = new HisIpInfo();
        if (CollectionUtil.isNotEmpty(allRight)) {
            allRight.sort(new Comparator<HisIpInfo>() {
                @Override
                public int compare(HisIpInfo o1, HisIpInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
            BeanUtils.copyProperties(allRight.get(0),right);
        }
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime newCreatTime = LocalDateTime.of(LocalDate.parse(startDate, dateFormatter), LocalTime.MIDNIGHT);
        // 前面逻辑保证left riht不会同时为空
        // 优先取左侧数据填充
        if (Objects.isNull(left.getId())) {
            right.setCreateTime(newCreatTime);
            betweenStartAndEnd.add(0, right);
        } else {
            left.setCreateTime(newCreatTime);
            betweenStartAndEnd.add(0, left);
        }
        return betweenStartAndEnd;
    }

    /**
     * 一天分摊多次的 只保留当天最后一次分摊的记录。
     * @param source
     * @return
     */
    public List<HisIpInfo> lastRecordsAtOneDay(List<HisIpInfo> source){
        if (CollectionUtil.isEmpty(source)) {
            return source;
        }
        Map<String, List<HisIpInfo>> date2List = source.stream()
                .filter(x -> Objects.nonNull(x.getCreateTime()))
                .collect(Collectors.groupingBy(x -> x.getCreateTime().toLocalDate().toString()));
        List<HisIpInfo> resutl = new ArrayList<>();
        for (String date : date2List.keySet()) {
            HisIpInfo temp = new HisIpInfo();
            List<HisIpInfo> hisIpInfos = date2List.get(date);
            //同一日期只有一个分摊比例
            if (hisIpInfos.size() == 1) {
                temp = hisIpInfos.get(0);
            }else{ //同一日期有多次分摊比例 只取最后一个操作
                hisIpInfos.sort(new Comparator<HisIpInfo>() {
                    @Override
                    public int compare(HisIpInfo o1, HisIpInfo o2) {
                        return o1.getCreateTime().compareTo(o2.getCreateTime());
                    }
                });
                temp = hisIpInfos.get(hisIpInfos.size() - 1);
            }
            resutl.add(temp);
        }
        return resutl;
    }


    /**
     * 参数校验
     * @param costAllocationTaskQueryDto
     */
    public void checkParam(CostAllocationTaskQueryDto costAllocationTaskQueryDto){
        String startDate = costAllocationTaskQueryDto.getStartDate();
        if(StringUtils.isBlank(startDate)){
            throw PlatformException.error("请传入开始时间");
        }
        String endDate = costAllocationTaskQueryDto.getEndDate();
        if(StringUtils.isBlank(endDate)){
            throw PlatformException.error("请传入结束时间");
        }
        if (startDate.compareTo(endDate) >=0) {
            throw PlatformException.error("结束时间要求晚于开始时间");
        }
        String taskName = costAllocationTaskQueryDto.getTaskName();
        if(StringUtils.isBlank(taskName)){
            throw PlatformException.error("请传入任务名称");
        }else{
            List<CostAllocationTask> depCostAllocations = costAllocationTaskRepo.queryByTaskName(taskName);
            if(CollectionUtil.isNotEmpty(depCostAllocations)){
                throw PlatformException.error("该任务名称已存在，请重新命名");
            }
        }
    }

    /**
     * 导出查询数据给云管
     * @param costAllocationTaskQueryDto
     * @return
     */
    public List<CostAllocationTaskExportDto> queryExportData(CostAllocationTaskQueryDto costAllocationTaskQueryDto) {
        String taskName = costAllocationTaskQueryDto.getTaskName();
        if(StringUtils.isBlank(taskName)){
            throw PlatformException.error("请输入任务名称");
        }
        String startDate = costAllocationTaskQueryDto.getStartDate();
        if(StringUtils.isBlank(startDate)){
            throw PlatformException.error("请完成输入开始时间");
        }
        String endDate = costAllocationTaskQueryDto.getEndDate();
        if(StringUtils.isBlank(endDate)){
            throw PlatformException.error("请完成输入结束时间");
        }
        List<CostAllocationTask> byName = costAllocationTaskRepo.queryByTaskName(taskName);
        if(CollectionUtil.isEmpty(byName) ){
            throw PlatformException.error("未找到当前任务名称的数据分摊明细");
        }
        List<CostAllocationTask> depCostAllocations = costAllocationTaskRepo.queryBytaskNameAndstartDateAndendDate(taskName, startDate, endDate);
        if( CollectionUtil.isEmpty(depCostAllocations)){
            throw PlatformException.error("未找到数据分摊明细");
        }

        List<CostAllocationTaskExportDto> result = new ArrayList();
        CostAllocationTaskExportDto firstRow = new CostAllocationTaskExportDto();
        firstRow.setItUniqueKey(taskName);
        firstRow.setSectionStartDate(startDate);
        firstRow.setSectionEndDate(endDate);
        result.add(firstRow);
        for(CostAllocationTask temp : depCostAllocations){
            CostAllocationTaskExportDto toReturn = new CostAllocationTaskExportDto();
            toReturn.setItUniqueKey(temp.getItUniqueKey());
            toReturn.setSectionStartDate(temp.getSectionStartDate());
            toReturn.setSectionEndDate(temp.getSectionEndDate());
            result.add(toReturn);
        }
        return result.stream().distinct().collect(Collectors.toList());
    }


    @Transactional
    public ReportUploadContext<UploadReturnAmountDto, String> uploadReturnAmount(MultipartFile file) throws IOException {
        ReportUploadContext<UploadReturnAmountDto, String> context = ReportUploadContext.<UploadReturnAmountDto, String>builder()
                .config(ReportFileConfigEnum.RETURN_AMOUNT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(context);
        AssertOverride.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<UploadReturnAmountDto> readResList = context.getReadRes();
        //后期数据量大 考虑异步执行

        UploadReturnAmountDto firstRow = readResList.get(0);
        //taskName
        String itUniqueKey = firstRow.getItUniqueKey();
        String sectionStartDate = firstRow.getSectionStartDate();
        String sectionEndDate = firstRow.getSectionEndDate();
        List<CostAllocationTask> costAllocationTasks = costAllocationTaskRepo.queryBytaskNameAndstartDateAndendDate(
                itUniqueKey, sectionStartDate, sectionEndDate);
        //处理不一致数据
        compareUploadAndLocal(itUniqueKey,sectionStartDate,sectionEndDate,readResList,costAllocationTasks);
        Map<String, String> amountMap = new HashMap<>();
        for(UploadReturnAmountDto item : readResList){
            String key = item.getItUniqueKey() + item.getSectionStartDate() + item.getSectionEndDate();
            String serverAmount = item.getServerAmount();
            amountMap.put(key,serverAmount);
        }

        for(CostAllocationTask temp :costAllocationTasks ){
            String itUniqueKeyTemp = temp.getItUniqueKey();
            String sectionStartDateTemp = temp.getSectionStartDate();
            String sectionEndDateTemp = temp.getSectionEndDate();
            String key = itUniqueKeyTemp + sectionStartDateTemp + sectionEndDateTemp;
            String val = amountMap.get(key);
            if(!StringUtils.isBlank(val)){
                temp.setServerAmount(new BigDecimal(val));
            }
            BigDecimal depAllocation = temp.getDepAllocation();
            BigDecimal systemAllocation = temp.getSystemAllocation();
            if(Objects.nonNull(depAllocation)
                    && Objects.nonNull(systemAllocation)
                    &&!StringUtils.isBlank(val)){
                BigDecimal account = new BigDecimal(val);
                BigDecimal bigDecimal = depAllocation
                        .multiply(systemAllocation)
                        .multiply(account)
                        .divide(new BigDecimal("10000"))
                        .setScale(2,RoundingMode.HALF_UP);
                temp.setDepAmount(bigDecimal);
            }
        }
        costAllocationTaskRepo.saveAllAndFlush(costAllocationTasks);
        return context;
    }

    /**
     * 全在导入云管多出来的数据时，先新增资产-编辑系统分摊|编辑服务资源分摊，
     * 保证两个分摊的的当前表有分摊数据。
     * 然后导入多出的数据。
     * 注意当服务器资源选择默认系统时，分摊部门使用从IT资产的负责人所属部门，
     * 而不是系统系统分摊数据的填写者
     * @param file
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<UploadReturnAmountDto, String> uploadReturnAmountSpecail(MultipartFile file) throws IOException {
        ReportUploadContext<UploadReturnAmountDto, String> context = ReportUploadContext.<UploadReturnAmountDto, String>builder()
                .config(ReportFileConfigEnum.RETURN_AMOUNT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(context);
        AssertOverride.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<UploadReturnAmountDto> readResList = context.getReadRes();
        PlatformUserDto user = userCache.get(request);
        String currUserOA = user.getUsername();
        //后期数据量大 考虑异步执行


        UploadReturnAmountDto firstRow = readResList.get(0);
        //taskName
        String taskName = firstRow.getItUniqueKey();
        String sectionStartDate = firstRow.getSectionStartDate();
        String sectionEndDate = firstRow.getSectionEndDate();
        List<CostAllocationTask> costAllocationTasks = costAllocationTaskRepo.queryBytaskNameAndstartDateAndendDate(taskName, sectionStartDate, sectionEndDate);
        if(CollectionUtil.isEmpty(costAllocationTasks)){
            throw PlatformException.errorWithOutMail("未找到相关分摊任务");
        }
        //删除首行 任务信息
        UploadReturnAmountDto remove = readResList.remove(0);
        Set<String> uniquekeySet = readResList.stream()
                .map(UploadReturnAmountDto::getItUniqueKey)
                .collect(Collectors.toSet());
        //一个资产只能出现一次
        int uniqueKeySize = uniquekeySet.size();
        int uploadSize = readResList.size();
        if (uniqueKeySize != uploadSize) {//说明有重复
            logger.info("资产uniqueKey大小：{}，导入数据大小：{}",uniqueKeySize,uploadSize);
            throw PlatformException.errorWithOutMail("请保证缺失资产唯一");
        }
        Set<String> savedKey = costAllocationTasks.stream()
                .map(CostAllocationTask::getItUniqueKey)
                .collect(Collectors.toSet());
        boolean present = uniquekeySet.stream().anyMatch(savedKey::contains);
        if(present){
            throw PlatformException.errorWithOutMail("存在已生成分摊比例的导入数据");
        }
        List<IpInfo> ipInfoList = ipInfoRepo.queryByUniquekeySet(uniquekeySet);
        List<IpDetailInfo> defalutDetailList = ipDetailInfoRepo.queryByDefaultSystem(defaultSystemNo);
        Set<Long> defaulltIPSet = defalutDetailList.stream()
                .map(IpDetailInfo::getIpInfoId)
                .collect(Collectors.toSet());
        Set<Long> ipinfoIdSet = new HashSet<>();
        Map<String, Long> itUniqueKey2Id = new HashMap<>();
        Map<String, String> itUniqueKey2IP = new HashMap<>();
        List<String> defaultUniqueKey = new ArrayList<>();
        for(IpInfo item : ipInfoList){
            String uniqueKey = item.getUniqueKey();
            Long id = item.getId();
            //默认系统单独处理
            if(defaulltIPSet.contains(id)){
                //选择了默认系统的资产id
                defaultUniqueKey.add(uniqueKey);
            }else{
                itUniqueKey2Id.put(uniqueKey,id);
                ipinfoIdSet.add(id);
            }
            itUniqueKey2IP.put(uniqueKey,item.getIp());
        }
        List<IpDetailInfo> ipDetailInfoList = ipDetailInfoRepo.queryByIpInfoIdWithoutDefaultSystem(ipinfoIdSet,defaultSystemNo);
        Map<Long, List<IpDetailInfo>> infoId2List = ipDetailInfoList.stream()
                .collect(Collectors.groupingBy(IpDetailInfo::getIpInfoId));

        List<BusiSystemInfo> all = busiSystemInfoRepo.findAll();
        Map<String, Long> sysNo2ID = all.stream()
                .collect(Collectors.toMap(BusiSystemInfo::getSystemClassNo, BusiSystemInfo::getId));
        Map<Integer, Long> depId2Count = getDepId2Count();
        //多部门勾选分摊是时 系统对应的分摊部门数据
        Map<String, Long> sysNo2DepCount = all.stream().filter(x -> StrUtil.isNotBlank(x.getSpecilaDep()))
                .collect(Collectors.toMap(BusiSystemInfo::getSystemClassNo, y -> {
                    JSONArray jsonArray = JSON.parseArray(y.getSpecilaDep());
                    List<AllDepDto> allDepDtos = jsonArray.toJavaList(AllDepDto.class);
                    //选中的一级部门id列表
                    Set<Integer> gradeOneIds = allDepDtos.stream()
                            .filter(x -> x.getKey().contains("#"))
                            .map(x -> {
                                String key = x.getKey();
                                return Integer.valueOf(key.substring(key.indexOf("#") + 1));
                            }).collect(Collectors.toSet());
                    Long count = 0L;
                    for(Integer i : gradeOneIds){
                        Long orDefault = depId2Count.getOrDefault(i, 0L);
                        count = count + orDefault;
                    }
                    return count;
                }));
        //多部门勾选分摊是时 系统对应的分摊部门数据
        Map<String, List<AllDepDto>> sysNo2AllDepDtoList = all.stream().filter(x -> StrUtil.isNotBlank(x.getSpecilaDep()))
                .collect(Collectors.toMap(BusiSystemInfo::getSystemClassNo, y -> {
                    JSONArray jsonArray = JSON.parseArray(y.getSpecilaDep());
                    return jsonArray.toJavaList(AllDepDto.class);
                }));
        //勾选方式的系统
        Set<String> systemIdCheckSet = sysNo2DepCount.keySet();

        List<DepCostAllocation> depAll = depCostAllocationRepo.findAll();
        Map<Long, List<DepCostAllocation>> sysID2List = depAll.stream()
                .collect(Collectors.groupingBy(DepCostAllocation::getSystemInfoId));
        //手动编辑的系统
        Set<Long> systemIdEditSet = sysID2List.keySet();
        BigDecimal bd100 = new BigDecimal("100");
        List<CostAllocationTask> toSaveList = new ArrayList();
        List<UploadReturnAmountDto> defaultDto = new ArrayList();
        for(UploadReturnAmountDto item : readResList){
            String itUniqueKey = item.getItUniqueKey();
            if(defaultUniqueKey.contains(itUniqueKey)){
                logger.info("采用默认系统分配方法");
                defaultDto.add(item);
                continue;
            }
            String serverAmounttemp = item.getServerAmount();
            if(StrUtil.isBlank(itUniqueKey) ||StrUtil.isBlank(serverAmounttemp)){
                logger.info("云管返回数据不全标识：{}，服务器金额：{}", itUniqueKey, serverAmounttemp);
                continue;
            }
            BigDecimal serverAmount = new BigDecimal(serverAmounttemp);
            Long aLong = itUniqueKey2Id.get(itUniqueKey);
            List<IpDetailInfo> ipDetailInfoList1 = infoId2List.get(aLong);
            //按照系统-组件分组  因为一个系统可以有多个组件
            Map<String, Map<String, List<IpDetailInfo>>> sysNo2Component2List = ipDetailInfoList1.stream()
                    .collect(Collectors.groupingBy(IpDetailInfo::getSystemClassNo,
                    Collectors.groupingBy(IpDetailInfo::getComponentName)));
            List<CostAllocationDateSeg> firstAllocationList = new ArrayList<>();
            for (String systemNo : sysNo2Component2List.keySet()) {
                Map<String, List<IpDetailInfo>> componet2List = sysNo2Component2List.get(systemNo);
                for(String componentName : componet2List.keySet()){
                    List<IpDetailInfo> sameSystemAndComponent = componet2List.get(componentName);
                    for(IpDetailInfo ipDetailInfo : sameSystemAndComponent){
                        CostAllocationDateSeg systemTemp = new CostAllocationDateSeg();
                        systemTemp.setUniqueKey(itUniqueKey);
                        systemTemp.setSystemClassNo(systemNo);
                        systemTemp.setComponentName(componentName);
                        systemTemp.setSystemAllocation(ipDetailInfo.getSourceAllocation());
                        firstAllocationList.add(systemTemp);
                    }
                }
            }

            for(CostAllocationDateSeg cad: firstAllocationList){
                String systemClassNo = cad.getSystemClassNo();
                BigDecimal systemAllocation = cad.getSystemAllocation();
                String componentName = cad.getComponentName();
                String uniqueKey = cad.getUniqueKey();
                Long orDefault = sysNo2ID.getOrDefault(systemClassNo, null);
                //系统到部门的分摊比例是编辑形式
                if(Objects.nonNull(orDefault) && systemIdEditSet.contains(orDefault)){
                    List<DepCostAllocation> depCostAllocations = sysID2List.get(orDefault);
                    for(DepCostAllocation dca :depCostAllocations){
                        CostAllocationTask toSave = new CostAllocationTask();
                        toSave.setSystemClassNo(systemClassNo);
                        toSave.setSectionStartDate(sectionStartDate);
                        toSave.setSectionEndDate(sectionEndDate);
                        toSave.setItUniqueKey(uniqueKey);
                        toSave.setVcIp(itUniqueKey2IP.get(uniqueKey));
                        toSave.setVcComponentName(componentName);
                        toSave.setCreateTime(LocalDateTime.now());
                        toSave.setDepGradeOneId(dca.getDepGradeOneId());
                        BigDecimal costAllocation = dca.getCostAllocation();
                        toSave.setDepAllocation(costAllocation);
                        toSave.setSystemAllocation(systemAllocation);
                        toSave.setTaskName(taskName);
                        toSave.setDataSource("03");
                        toSave.setEndDate(sectionEndDate);
                        toSave.setStartDate(sectionStartDate);
                        toSave.setOperator(currUserOA);
                        toSave.setServerAmount(serverAmount);

                        if(Objects.nonNull(costAllocation) && Objects.nonNull(systemAllocation)){
                            BigDecimal bigDecimal = serverAmount
                                    .multiply(costAllocation)
                                    .multiply(systemAllocation)
                                    .divide(new BigDecimal("10000"))
                                    .setScale(2,RoundingMode.HALF_UP);
                            toSave.setDepAmount(bigDecimal);
                        }

                        toSaveList.add(toSave);
                    }
                }else if(systemIdCheckSet.contains(systemClassNo)){
                    Long allDepCount = sysNo2DepCount.get(systemClassNo);
                    if (allDepCount.compareTo(0L) == 0) {
                        logger.info("一般不出现的情况，{}",systemClassNo);
                        continue;
                    }
                    List<AllDepDto> allDepDtos = sysNo2AllDepDtoList.get(systemClassNo);
                    //选中的一级部门id列表
                    Set<Integer> gradeOneIds = allDepDtos.stream()
                            .filter(x -> x.getKey().contains("#"))
                            .map(x -> {
                                String key = x.getKey();
                                return Integer.valueOf(key.substring(key.indexOf("#") + 1));
                            }).collect(Collectors.toSet());
                    for(Integer i : gradeOneIds){
                        Long depSize = depId2Count.getOrDefault(i, 0L);
                        if (depSize.compareTo(0L) == 0) {
                            continue;
                        }
                        BigDecimal tempDep = new BigDecimal(depSize);
                        BigDecimal divide = tempDep.divide(new BigDecimal(sysNo2DepCount.get(systemClassNo)),
                                6, RoundingMode.HALF_UP).multiply(bd100);
                        CostAllocationTask toSave = new CostAllocationTask();
                        toSave.setSystemClassNo(systemClassNo);
                        toSave.setSectionStartDate(sectionStartDate);
                        toSave.setSectionEndDate(sectionEndDate);
                        toSave.setItUniqueKey(uniqueKey);
                        toSave.setVcIp(itUniqueKey2IP.get(uniqueKey));
                        toSave.setVcComponentName(componentName);
                        toSave.setCreateTime(LocalDateTime.now());
                        toSave.setDepGradeOneId(String.valueOf(i));
                        toSave.setDepAllocation(divide);
                        toSave.setSystemAllocation(systemAllocation);
                        toSave.setTaskName(taskName);
                        toSave.setDataSource("03");
                        toSave.setEndDate(sectionEndDate);
                        toSave.setStartDate(sectionStartDate);
                        toSave.setOperator(currUserOA);
                        toSave.setServerAmount(serverAmount);

                        if(Objects.nonNull(divide) && Objects.nonNull(systemAllocation)){
                            BigDecimal bigDecimal = serverAmount
                                    .multiply(divide)
                                    .multiply(systemAllocation)
                                    .divide(new BigDecimal("10000"))
                                    .setScale(2,RoundingMode.HALF_UP);
                            toSave.setDepAmount(bigDecimal);
                        }

                        toSaveList.add(toSave);
                    }
                }
            }
        }
        if(CollectionUtil.isNotEmpty(defaultDto)){
            List<CostAllocationTask> specialSystemList = handleDefaultSystem(defaultDto,sectionStartDate,
                    sectionEndDate,itUniqueKey2IP,currUserOA,taskName);
            if (CollectionUtil.isNotEmpty(specialSystemList)) {
                toSaveList.addAll(specialSystemList);
            }
        }
        costAllocationTaskRepo.saveAllAndFlush(toSaveList);
        return context;
    }

    /**
     * 导入的云管数据中，
     * 处理分摊到默认系统的资产
     * @param defaultDto
     * @param startDate
     * @param endDate
     * @param itUniqueKey2IP
     * @param currUserOA
     * @param taskName
     * @return
     */
    private List<CostAllocationTask> handleDefaultSystem(List<UploadReturnAmountDto> defaultDto,String startDate,
                                                         String endDate,Map<String, String> itUniqueKey2IP,
                                                         String currUserOA,String taskName) {
        //虚拟机资产编号
        Set<String> vdKey = new HashSet<>();
        //物理机资产编号
        Set<Integer> phyKey = new HashSet<>();
        for(UploadReturnAmountDto item : defaultDto){
            String itUniqueKey = item.getItUniqueKey();
            if(itUniqueKey.startsWith("VD")){
                vdKey.add(itUniqueKey);
            }else{
                phyKey.add(Integer.valueOf(itUniqueKey));
            }
        }
        List<ItVirtualDevice> itVirtualDevices = itVirtualDeviceRepo.queryByIds(vdKey);
        List<ItServerDevice> itServerDevices = itServerDeviceRepo.queryByIds(phyKey);
        Map<String, String> vd2UserId = itVirtualDevices.stream()
                .collect(Collectors.toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getUserId));
        Map<String, String> phy2UserId = itServerDevices.stream()
                .collect(Collectors.toMap(x-> x.getDevId().toString(), ItServerDevice::getUserId));
        Map<String, Integer> userOaId2DdepOne = oaUserID2DepGradeOne();

        BigDecimal bd100 = new BigDecimal("100");
        List<CostAllocationTask> result = new ArrayList<>();
        for(UploadReturnAmountDto item : defaultDto){
            String itUniqueKey = item.getItUniqueKey();
            String serverAmountTemp = item.getServerAmount();
            if(StrUtil.isBlank(serverAmountTemp)){
                logger.info("当前资产金额为空，{}",itUniqueKey);
                continue;
            }
            String userOaId = "";
            if(itUniqueKey.startsWith("VD")){
                 userOaId = vd2UserId.get(itUniqueKey);
            }else{
                userOaId = phy2UserId.get(itUniqueKey);
            }
            if(StrUtil.isBlank(userOaId)){
                logger.info("当前资产未找到责任人，{}",itUniqueKey);
                continue;
            }
            Integer depOneId = userOaId2DdepOne.get(userOaId);
            CostAllocationTask toSave = new CostAllocationTask();
            toSave.setSystemClassNo(defaultSystemNo);
            toSave.setSectionStartDate(startDate);
            toSave.setSectionEndDate(endDate);
            toSave.setItUniqueKey(itUniqueKey);
            toSave.setVcIp(itUniqueKey2IP.get(itUniqueKey));
            toSave.setVcComponentName("操作机");
            toSave.setCreateTime(LocalDateTime.now());
            toSave.setDepGradeOneId(String.valueOf(depOneId));
            toSave.setDepAllocation(bd100);
            toSave.setSystemAllocation(bd100);
            toSave.setTaskName(taskName);
            toSave.setDataSource("03");
            toSave.setEndDate(endDate);
            toSave.setStartDate(startDate);
            toSave.setOperator(currUserOA);
            BigDecimal serverAmount = new BigDecimal(serverAmountTemp);
            toSave.setDepAmount(serverAmount);
            toSave.setServerAmount(serverAmount);
            result.add(toSave);
        }
        logger.info("采用默认分摊的大小为：{}", defaultDto.size());
        return result;
    }

    /**
     * 比较云管返回数据和已落库数据的差异
     *
     * @param readResList
     * @param costAllocationTasks
     */
    private void compareUploadAndLocal(String taskName,String startDate,String endDate,
                                      List<UploadReturnAmountDto> readResList,
                                      List<CostAllocationTask> costAllocationTasks) {
        Set<String> returnAll = readResList.stream()
                .map(x -> {
                    return x.getItUniqueKey() + x.getSectionStartDate() + x.getSectionEndDate();
                })
                .collect(Collectors.toSet());

        Map<String, String> key2Value = new HashMap<>();
        for(UploadReturnAmountDto tempURA : readResList){
            String key = tempURA.getItUniqueKey()
                    + tempURA.getSectionStartDate()
                    + tempURA.getSectionEndDate();
            key2Value.put(key,tempURA.getServerAmount());
        }

       /* Set<String> localAll = costAllocationTasks.stream().map(x -> {
            return x.getItUniqueKey() + x.getSectionStartDate() + x.getSectionEndDate();
        }).collect(Collectors.toSet());
        List<CostAllocationTask> toSaveList = new ArrayList<>();
        for(UploadReturnAmountDto  temp : readResList){
            String itUniqueKey = temp.getItUniqueKey();
            //首行跳过
            if(taskName.equals(itUniqueKey)){
                continue;
            }
            String returnKey = itUniqueKey + temp.getSectionStartDate() + temp.getSectionEndDate();
            //云管返回数据 本地没有 本地另外保存
            if(!localAll.contains(returnKey)){
                CostAllocationTask toSave = new CostAllocationTask();
                toSave.setTaskName(taskName);
                toSave.setItUniqueKey(itUniqueKey);
                toSave.setStartDate(startDate);
                toSave.setEndDate(endDate);
                toSave.setCreateTime(LocalDateTime.now());
                toSave.setDataSource("03");
                toSaveList.add(toSave);
            }
        }
        costAllocationTaskRepo.saveAll(toSaveList);*/

        for(CostAllocationTask tempCAT : costAllocationTasks){
            String localKey = tempCAT.getItUniqueKey() + tempCAT.getSectionStartDate() + tempCAT.getSectionEndDate();
            //云管没有返回数据 或 返回数据没有金额
            boolean localMore = !returnAll.contains(localKey) || StringUtils.isBlank(key2Value.get(localKey));
            if(localMore){
                tempCAT.setDataSource("02");
            }
        }
    }

    public boolean checkReturnPass(List<UploadReturnAmountDto> readResList,List<CostAllocationTask> costAllocationTasks){
        int returnSize = readResList.size();
        int localSize = costAllocationTasks.size();
        //返回数据-1 至少要大于本地数据
        int sub = returnSize - localSize - 1;
        if (sub < 0) {
            logger.info("校验返回数据-数据不足");
            return false;
        }
        //传输列表数据任一内容都不能为空
        boolean existNull = readResList.stream().anyMatch(x -> {
            return StringUtils.isBlank(x.getServerAmount())
                    || StringUtils.isBlank(x.getSectionStartDate())
                    || StringUtils.isBlank(x.getItUniqueKey())
                    || StringUtils.isBlank(x.getSectionEndDate());
        });
        if(existNull){
            logger.info("校验返回数据-数据存在null");
            return false;
        }
        return true;
    }

    /**
     * 获取全部任务的名称
     * @return
     */
    public List<String> getAllTasks() {
        List<CostAllocationTask> all = costAllocationTaskRepo.findAll();
        return all.stream()
                .map(CostAllocationTask::getTaskName)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
    }

    public Page<SystemStaticDto> systemListPage(String taskName, String systemClassNo,
                                                String ip,String pageSizeQuery,
                                                String pageNoQuery ) {
        logger.info("系统维度统计：{}-{}-{}", taskName, systemClassNo, ip);
        List<SystemStaticDto> result = this.getSystemStaticData(taskName,systemClassNo,ip);
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "systemClassNo";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        return PageUtil.listConvertToPage(result, pageable);
    }

    public List<SystemStaticDto> getSystemStaticData(String taskName, String systemClassNo,
                                                     String ip){
        List<CostAllocationTask> query = costAllocationTaskRepo.queryByTaskName(taskName);
        if(StringUtils.isNotBlank(systemClassNo)){
            query = query.stream()
                    .filter(x -> systemClassNo.equals(x.getSystemClassNo()))
                    .collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(ip)) {
            query = query.stream()
                    .filter(x -> ip.equals(x.getVcIp()))
                    .collect(Collectors.toList());
        }
        List<SystemStaticDto> result = new ArrayList<>();
        List<SystemMain> systemMainList = systemMainService.queryAll();
        Map<String,String> systemNameMap = systemMainList.stream()
                .collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));
        Map<String, List<CostAllocationTask>> systemNo2List = query.stream()
                .collect(Collectors.groupingBy(CostAllocationTask::getSystemClassNo));
        for (String systemNo : systemNo2List.keySet()) {
            //同一个系统
            List<CostAllocationTask> costAllocationTasks = systemNo2List.get(systemNo);
            Map<String, List<CostAllocationTask>> ip2List = costAllocationTasks.stream()
                    .collect(Collectors.groupingBy(CostAllocationTask::getVcIp));
            for (String ipTemp : ip2List.keySet()) {
                SystemStaticDto toReturn = new SystemStaticDto();
                //同一个ip
                List<CostAllocationTask> catFromIP = ip2List.get(ipTemp);
                BigDecimal totalIP = null;
                if(CollectionUtil.isNotEmpty(catFromIP)){
                    totalIP = catFromIP.stream()
                            .map(CostAllocationTask::getDepAmount)
                            .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                    toReturn.setTotalNum(totalIP.toPlainString());
                    CostAllocationTask costAllocationTask = catFromIP.get(0);
                    toReturn.setItUniqueKey(costAllocationTask.getItUniqueKey());
                    toReturn.setStartDate(costAllocationTask.getStartDate());
                    toReturn.setEndDate(costAllocationTask.getEndDate());
                }
                toReturn.setTaskName(taskName);
                toReturn.setSystemClassNo(systemNo);
                toReturn.setSystemName(systemNameMap.get(systemNo));
                toReturn.setIp(ipTemp);
                toReturn.setUniqueKey(UUID.randomUUID().toString());
                result.add(toReturn);
            }
        }
        return result;
    }

    /**
     * 系统维度导出数据
     * @param taskName
     * @param systemClassNo
     * @param ip
     * @return
     */
    public List<CostAllocationTaskSystemExportDto> getExportSystemStatic(String taskName, String systemClassNo,
                                      String ip){
        List<SystemStaticDto> systemStaticData = this.getSystemStaticData(taskName,systemClassNo,ip);
        List<CostAllocationTaskSystemExportDto> result = new ArrayList<>();
        for(SystemStaticDto item : systemStaticData){
            CostAllocationTaskSystemExportDto toRe = new CostAllocationTaskSystemExportDto();
            toRe.setIP(item.getIp());
            toRe.setSystemName(item.getSystemName());
            toRe.setTotalNum(item.getTotalNum());
            result.add(toRe);
        }
        return result;
    }

    /**
     * 查询指定明细
     * @param taskName
     * @param systemClassNo
     * @param ip
     * @return
     */
    public Page<SystemDetailStaticDto> systemDetailListPage(String taskName,
                                                            String systemClassNo,
                                                            String ip,
                                                            String pageSizeQuery,
                                                            String pageNoQuery) {
        logger.info("系统维度统计：{}-{}-{}", taskName, systemClassNo, ip);

        List<CostAllocationTask> queryList = costAllocationTaskRepo.queryByTaskNameAndSystemNoAndIp(taskName, systemClassNo, ip);
        String regex = "#";
        Map<String, List<CostAllocationTask>> groupByThree = queryList.stream().collect(Collectors.groupingBy(x -> {
            return x.getSectionStartDate() +
                    regex + x.getSectionEndDate() + regex + x.getVcComponentName();
        }));
        BigDecimal oneHundred = new BigDecimal("100");
        List<SystemDetailStaticDto> resutl = new ArrayList<>();
        for (String key : groupByThree.keySet()) {
            String[] split = key.split(regex);
            List<CostAllocationTask> costAllocationTasks = groupByThree.get(key);
            //此时计算系统对IP的占用  这一组数据占用值是一致的
            CostAllocationTask firstOne = costAllocationTasks.get(0);
            SystemDetailStaticDto toReturn = new SystemDetailStaticDto();
            toReturn.setUniqueKey(UUID.randomUUID().toString());
            BigDecimal serverAmount = firstOne.getServerAmount();
            toReturn.setServerAmount(serverAmount);
            BigDecimal systemAllocation = firstOne.getSystemAllocation();
            toReturn.setSystemAllocation(systemAllocation);
            toReturn.setSystemName(firstOne.getSystemName());
            toReturn.setVcIp(ip);
            toReturn.setSectionStartDate(split[0]);
            toReturn.setSectionEndDate(split[1]);
            toReturn.setVcComponentName(split[2]);
            if(Objects.nonNull(serverAmount) && Objects.nonNull(systemAllocation)){
                toReturn.setSystemAmount(serverAmount
                        .multiply(systemAllocation)
                        .divide(oneHundred,6,RoundingMode.HALF_UP)
                        .toPlainString());
            }
            resutl.add(toReturn);
        }
        resutl.sort(Comparator.comparing(SystemDetailStaticDto::getVcComponentName)
                .thenComparing(SystemDetailStaticDto::getSectionStartDate));

        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "systemClassNo";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        return PageUtil.listConvertToPage(resutl, pageable);
    }

    public Page<DepartmentStaticDto> depListPage(String taskName, String systemClassNo,
                                             String depOneId, String pageSizeQuery,
                                             String pageNoQuery) {

        logger.info("部门维度统计：{}-{}-{}", taskName, systemClassNo,depOneId);
        List<DepartmentStaticDto> result = this.getDepStaticData(taskName,systemClassNo,depOneId);
        result.sort((o1, o2) -> {
            Collator instance = Collator.getInstance(Locale.CHINA);
            return instance.compare(o1.getDepGradeOneName(), o2.getDepGradeOneName());
        });
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "depGradeOneId";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        return PageUtil.listConvertToPage(result, pageable);
    }

    /**
     * 统计部门维度数据
     * @param taskName
     * @param systemClassNo
     * @param depOneId
     * @return
     */
    public List<DepartmentStaticDto> getDepStaticData(String taskName, String systemClassNo,
                                                      String depOneId){
        List<CostAllocationTask> query = costAllocationTaskRepo.queryByTaskName(taskName);
        if(StringUtils.isNotBlank(systemClassNo)){
            query = query.stream()
                    .filter(x -> systemClassNo.equals(x.getSystemClassNo()))
                    .collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(depOneId)) {
            query = query.stream()
                    .filter(x -> depOneId.equals(x.getDepGradeOneId()))
                    .collect(Collectors.toList());
        }
        if (CollectionUtil.isEmpty(query)) {
            return new ArrayList<>();
        }

        List<SystemMain> systemMainList = systemMainService.queryAll();
        Map<String,String> systemNameMap = systemMainList.stream()
                .collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));
        CostAllocationTask anyOne = query.get(0);
        String endDate = anyOne.getEndDate();
        String startDate = anyOne.getStartDate();
        LdapResponse<List<LdapEhrDeptDto>> deptList = iFeignLdapService.getDepartmentList(new LdapEhrDeptSearchDto());
        Map<String,String> deptNameMap = deptList.getData().stream()
                .filter(x -> {return "一级部门".equals(x.getDepgrade());})
                .map(e->{
                    e.setDtitle(e.getDtitle().trim());
                    return e;
                }).collect(Collectors.toMap(x ->x.getDepid().toString(),x->{
                    String dtitle =  x.getDtitle();
                    String comptitle = x.getComptitle();
                    return dtitle.contains(comptitle)?dtitle:comptitle+"/"+dtitle;
                }));
        //部门分组
        Map<String, List<CostAllocationTask>> depId2List = query.stream()
                .collect(Collectors.groupingBy(CostAllocationTask::getDepGradeOneId));
        List<DepartmentStaticDto> result = new ArrayList<>();
        for (String depId : depId2List.keySet()) {
            List<CostAllocationTask> depIdList = depId2List.get(depId);
            //部门下 系统分组
            Map<String, List<CostAllocationTask>> systemNo2List = depIdList.stream()
                    .collect(Collectors.groupingBy(CostAllocationTask::getSystemClassNo));
            for (String systemNo : systemNo2List.keySet()) {
                List<CostAllocationTask> costAllocationTasks = systemNo2List.get(systemNo);
                BigDecimal depSystemTotal = costAllocationTasks.stream()
                        .map(CostAllocationTask::getDepAmount)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                DepartmentStaticDto toReturn = new DepartmentStaticDto();
                toReturn.setTaskName(taskName);
                toReturn.setEndDate(endDate);
                toReturn.setStartDate(startDate);
                toReturn.setDepGradeOneId(depId);
                toReturn.setSystemClassNo(systemNo);
                toReturn.setTotalNum(depSystemTotal.toPlainString());
                toReturn.setUniqueKey(UUID.randomUUID().toString());
                toReturn.setSystemName(systemNameMap.get(systemNo));
                toReturn.setDepGradeOneName(deptNameMap.get(depId));
                result.add(toReturn);
            }
        }
        return result;
    }

    public List<CostAllocationTaskDepExportDto> getDepStaticExportData(String taskName, String depOneId,
                                                              String systemClassNo){
        List<DepartmentStaticDto> depStaticData = this.getDepStaticData(taskName, systemClassNo, depOneId);
        List<CostAllocationTaskDepExportDto> result = new ArrayList<>();
        for(DepartmentStaticDto item : depStaticData){
            CostAllocationTaskDepExportDto toRe = new CostAllocationTaskDepExportDto();
            toRe.setDepGradeOneName(item.getDepGradeOneName());
            toRe.setTotalNum(item.getTotalNum());
            toRe.setSystemName(item.getSystemName());
            result.add(toRe);
        }
        return result;

    }

    public Page<DepartmentStaticDetailDto> depDetailListPage(String taskName, String systemClassNo,
                                                         String depGradeOneId,String vcIp,String itUniqueKey,
                                                         String pageSizeQuery, String pageNoQuery) {
        logger.info("部门维度统计明细：{}-{}-{}-{}-{}", taskName, systemClassNo,depGradeOneId,vcIp,itUniqueKey);
        List<CostAllocationTask> query = costAllocationTaskRepo
                .queryByTaskNameAndDepOneIdAndSystemNo(taskName,depGradeOneId,systemClassNo);
        if(StringUtils.isNotBlank(vcIp)){
            query = query.stream().filter(x -> vcIp.equals(x.getVcIp())).collect(Collectors.toList());
        }
        if(StringUtils.isNotBlank(itUniqueKey)){
            query = query.stream().filter(x -> itUniqueKey.equals(x.getItUniqueKey())).collect(Collectors.toList());
        }
        if(CollectionUtil.isEmpty(query)){
            return new PageImpl<>(new ArrayList<>());
        }
        LdapResponse<List<LdapEhrDeptDto>> deptList = iFeignLdapService.getDepartmentList(new LdapEhrDeptSearchDto());
        Map<String,String> deptNameMap = deptList.getData().stream()
                .filter(x -> {return "一级部门".equals(x.getDepgrade());})
                .map(e->{
                    e.setDtitle(e.getDtitle().trim());
                    return e;
                }).collect(Collectors.toMap(x ->x.getDepid().toString(),x->{
                    String dtitle =  x.getDtitle();
                    String comptitle = x.getComptitle();
                    return dtitle.contains(comptitle)?dtitle:comptitle+"/"+dtitle;
                }));

        List<DepartmentStaticDetailDto> result = new ArrayList<>();
        List<SystemMain> systemMainList = systemMainService.queryAll();
        Map<String,String> systemNameMap = systemMainList.stream()
                .collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));
        Map<String, List<CostAllocationTask>> itKey2List = query.stream()
                .collect(Collectors.groupingBy(CostAllocationTask::getItUniqueKey));
        for (String itUniqueKeyItem : itKey2List.keySet()) {
            List<CostAllocationTask> costAllocationTasks = itKey2List.get(itUniqueKeyItem);
            for(CostAllocationTask temp : costAllocationTasks){
                DepartmentStaticDetailDto toRe = new DepartmentStaticDetailDto();
                toRe.setSystemClassNo(systemClassNo);
                toRe.setDepAllocation(temp.getDepAllocation());
                toRe.setSystemAllocation(temp.getSystemAllocation());
                BigDecimal depAmount = temp.getDepAmount();
                toRe.setDepAmount(depAmount);
                BigDecimal serverAmount = temp.getServerAmount();
                toRe.setServerAmount(serverAmount);
                toRe.setDepGradeOneId(depGradeOneId);
                toRe.setIp(temp.getVcIp());
                toRe.setSectionStartDate(temp.getSectionStartDate());
                toRe.setSectionEndDate(temp.getSectionEndDate());
                toRe.setSystemName(systemNameMap.get(systemClassNo));
                toRe.setDepGradeOneName(deptNameMap.get(depGradeOneId));
                toRe.setUniqueKey(UUID.randomUUID().toString());
                toRe.setItUniqueKey(itUniqueKeyItem);
                result.add(toRe);
            }
        }
        result.sort(Comparator.comparing(DepartmentStaticDetailDto::getItUniqueKey)
                .thenComparing(DepartmentStaticDetailDto::getSectionStartDate));

        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "depGradeOneId";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        return PageUtil.listConvertToPage(result, pageable);
    }


    /**
     * useroaid 和 一级部门的映射
     * 1234:123
     * @return
     */
    public Map<String, Integer> oaUserID2DepGradeOne(){
        LdapResponse<List<LdapEhrEmpDto>> ehrList = iFeignLdapService.getUserList(new LdapEhrEmpSearchDto());
        List<LdapEhrEmpDto> data = ehrList.getData();
        Map<String,LdapEhrEmpDto> ehrMap = data.stream()
                .collect(Collectors.toMap(x->x.getOaUserId().toString(), Function.identity(), (key1, key2) -> key2));
        //二级部门的一级部门id
        Map<Integer, Integer> deptwo2depone = new HashMap<>();
        List<LdapEhrEmpDto> collect = data.stream().filter(x -> {
            LdapEhrDeptDto deptinfo = x.getDeptinfo();
            return Objects.nonNull(x.getDepid()) &&
                    (Objects.isNull(deptinfo) || "二级部门".equals(deptinfo.getDepgrade()));
        }).collect(Collectors.toList());
        for(LdapEhrEmpDto item : collect){
            Integer depid = item.getDepid();
            if(!deptwo2depone.containsKey(depid)){
                LdapEhrDeptDto deptinfo = item.getDeptinfo();
                deptwo2depone.put(depid,Objects.isNull(deptinfo)? depid : deptinfo.getSuperDeptId());
            }
        }
        Map<String, Integer> userOaId2Depid = new HashMap<>();
        for (String oaUserId : ehrMap.keySet()) {
            LdapEhrEmpDto ldapEhrEmpDto = ehrMap.get(oaUserId);
            LdapEhrDeptDto deptinfo = ldapEhrEmpDto.getDeptinfo();
            if(Objects.isNull(deptinfo)){
                userOaId2Depid.put(oaUserId,ldapEhrEmpDto.getDepid());
            }else{
                String depgrade = deptinfo.getDepgrade();
                Integer depTwotId = deptinfo.getSuperDeptId();
                if("一级部门".equals(depgrade)){
                    userOaId2Depid.put(oaUserId,ldapEhrEmpDto.getDepid());
                }else if("二级部门".equals(depgrade)){
                    userOaId2Depid.put(oaUserId, depTwotId);
                }else{//三级部门
                    userOaId2Depid.put(oaUserId, deptwo2depone.get(depTwotId));
                }
            }
        }
        return userOaId2Depid;
    }

    public List<ReplenishmentInfoExportDto> getReplenishmentData(ReplenishmentInfoQueryDto queryDto) {

        Map<String, Object> param = new HashMap<>();
        String queryDtoSystemClassNo = queryDto.getSystemClassNo();
        if(StrUtil.isNotEmpty(queryDtoSystemClassNo)){
            param.put("EQ_systemClassNo",queryDtoSystemClassNo);
        }

        String systemUserId = queryDto.getSystemUserId();
        if (StrUtil.isNotEmpty(systemUserId)) {
            param.put("EQ_systemUserId", systemUserId);
        }

        String ip = queryDto.getVcIp();
        if (StrUtil.isNotEmpty(ip)) {
            param.put("LIKE_vcIp", ip);
        }

        String dataSource = queryDto.getDataSource();
        if (StrUtil.isNotEmpty(dataSource)) {
            param.put("EQ_dataSource", dataSource);
        }

        String itUniqueKey = queryDto.getItUniqueKey();
        if (StrUtil.isNotEmpty(itUniqueKey)) {
            param.put("EQ_itUniqueKey", itUniqueKey);
        }
        String machineStatus = queryDto.getMachineStatus();
        if(StringUtils.isNotBlank(machineStatus)){
            param.put("EQ_machineStatus", machineStatus);
        }
        String machineType = queryDto.getMachineType();
        if(StringUtils.isNotBlank(machineType)){
            param.put("EQ_machineType", machineType);
        }
        List<ReplenishmentInfo> all = replenishmentInfoRepo.findAll(
                SpecificationUtil.buildSpecification(param, ReplenishmentInfo.class));
        List<ReplenishmentInfoExportDto> result = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(all)){
            List<SystemMain> systemMainList = systemMainService.queryAll();
            Map<String,String> systemNameMap = systemMainList.stream()
                    .collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));

            AppEhrResponse<List<LdapEhrEmpDto>> user = feignLdapService.getAllEmps();
            List<LdapEhrEmpDto> userData = user.getData();
            Map<String, String> oa2name = userData.stream()
                    .collect(Collectors.toMap(LdapEhrEmpDto::getBadge, LdapEhrEmpDto::getName));


            ItDictData byDictDataDeviceType = dictionaryService.findByDictData("设备类型");
            List<ItDict> dictValues = byDictDataDeviceType.getDictValues();
            //设备类型
            Map<Integer, String> deviceTypedictId2Value = dictValues.stream()
                    .collect(Collectors.toMap(ItDict::getZdId, ItDict::getDictValue));
            ItDictData byDictDataStatus = dictionaryService.findByDictData("状态");
            List<ItDict> byDictDataStatusValuse = byDictDataStatus.getDictValues();
            //服务器状态
            Map<Integer, String> statusdictId2Value = byDictDataStatusValuse.stream()
                    .collect(Collectors.toMap(ItDict::getZdId, ItDict::getDictValue));

            List<ItServerDevice> allServerList = itServerDeviceRepo.findAll();


           for (ReplenishmentInfo item : all) {
                ReplenishmentInfoExportDto toReturn = new ReplenishmentInfoExportDto();
               String itUniqueKeyItem = item.getItUniqueKey();
               toReturn.setItUniqueKey(itUniqueKeyItem);
               toReturn.setVcIp(item.getVcIp());
               toReturn.setDataSource(item.getDataSource());
               String systemClassNo = item.getSystemClassNo();
               toReturn.setSystemClassNo(systemNameMap.getOrDefault(systemClassNo,systemClassNo));
               String systemUserId1 = item.getSystemUserId();
               toReturn.setSystemUserId(oa2name.getOrDefault(systemUserId1,systemUserId1));

               if(item.getItUniqueKey().contains("VD")){
                   String machineStatus1 = item.getMachineStatus();
                   if("1".equals(machineStatus1)){
                       toReturn.setMachineStatus("虚拟机未删除");
                   }else if("2".equals(machineStatus1)){
                       toReturn.setMachineStatus("虚拟机已删除");
                   }else{
                       toReturn.setMachineStatus("虚拟机无状态");
                   }
                }else{
                    String machineStatusItem = item.getMachineStatus();
                    if(StrUtil.isNotBlank(machineStatusItem)){
                        Integer integer = Integer.valueOf(machineStatusItem);
                        toReturn.setMachineStatus(statusdictId2Value.getOrDefault(integer,null));
                    }
                   String machineType1 = item.getMachineType();
                    if(StrUtil.isNotBlank(machineType1)){
                        Integer machineTypeTemp = Integer.valueOf(machineType1);
                        toReturn.setMachineType(deviceTypedictId2Value.getOrDefault(machineTypeTemp,machineType1));
                    }
               }
               result.add(toReturn);
            }
        }
        return result;
    }

    /**
     * 保存云管多出来的数据，
     * 只保存当前最新导入的数据，直接全部删除上一次的数据
     * @param file
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<UploadReturnAmountDto, String> uploadReplenishment(MultipartFile file) throws IOException {
        ReportUploadContext<UploadReturnAmountDto, String> context = ReportUploadContext.<UploadReturnAmountDto, String>builder()
                .config(ReportFileConfigEnum.RETURN_AMOUNT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(context);
        AssertOverride.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<UploadReturnAmountDto> readResList = context.getReadRes();
        UploadReturnAmountDto firstRow = readResList.get(0);
        readResList.remove(0);

        List<ItServerDevice> allServerList = itServerDeviceRepo.findAll();
        //id-设备类型
        Map<Integer, String> serId2DevieceType = allServerList.stream()
                .filter(x->Objects.nonNull(x.getCapitalStyle()))
                .collect(Collectors
                .toMap(ItServerDevice::getDevId, ItServerDevice::getCapitalStyle));
       //id-状态
        Map<Integer, String> serId2DevieceStatus = allServerList.stream()
                .filter(x->Objects.nonNull(x.getMachineStatus()))
                .collect(Collectors
                .toMap(ItServerDevice::getDevId, ItServerDevice::getMachineStatus));
        //id-业务系统
        Map<Integer, String> serId2BusiNO = allServerList.stream()
                .filter(x->Objects.nonNull(x.getBusinessName()))
                .collect(Collectors
                .toMap(ItServerDevice::getDevId, ItServerDevice::getBusinessName));
        //id-ip1
        Map<Integer, String> serId2IP1 = allServerList.stream()
                .filter(x->Objects.nonNull(x.getIp1()))
                .collect(Collectors
                .toMap(ItServerDevice::getDevId, ItServerDevice::getIp1));
        //id-userID   4543
        Map<Integer, String> serId2UserId = allServerList.stream()
                .filter(x->Objects.nonNull(x.getUserId()))
                .collect(Collectors
                .toMap(ItServerDevice::getDevId, ItServerDevice::getUserId));


        List<ItVirtualDevice> allVirtual = itVirtualDeviceRepo.findAll();
        //id-userID   4543
        Map<String, String> virId2UserId = allVirtual.stream()
                .filter(x->Objects.nonNull(x.getUserId()))
                .collect(Collectors
                .toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getUserId));
        //id-删除状态   0已删除 1未删除
        Map<String, String> virId2MarkStatus = allVirtual.stream()
                .filter(x->Objects.nonNull(x.getMark()))
                .collect(Collectors
                .toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getMark));

        //id-业务系统
        Map<String, String> virId2BusiNo = allVirtual.stream()
                .filter(x->Objects.nonNull(x.getBusinessName()))
                .collect(Collectors
                .toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getBusinessName));

        //id-ip1
        Map<String, String> virId2IP1 = allVirtual.stream()
                .filter(x->Objects.nonNull(x.getIp1()))
                .collect(Collectors
                .toMap(ItVirtualDevice::getDevId, ItVirtualDevice::getIp1));

        Set<String> allVirID = allVirtual.stream()
                .map(ItVirtualDevice::getDevId).collect(Collectors.toSet());
        Set<Integer> allServerID = allServerList.stream()
                .map(ItServerDevice::getDevId).collect(Collectors.toSet());

        List<IpInfo> allIpinfo = ipInfoRepo.findAll();
        Set<String> allIpinfoKey = allIpinfo.stream().map(IpInfo::getUniqueKey)
                .collect(Collectors.toSet());
        Map<String, Long> key2INfoID = allIpinfo.stream()
                .collect(Collectors.toMap(IpInfo::getUniqueKey, IpInfo::getId));
        Set<Long> allInfoId = allIpinfo.stream().map(IpInfo::getId).collect(Collectors.toSet());
        List<IpDetailInfo> ipDetailInfoList = ipDetailInfoRepo.queryByIpInfoId(allInfoId);
        Map<Long, List<IpDetailInfo>> infoId2DetailList = ipDetailInfoList.stream()
                .collect(Collectors.groupingBy(IpDetailInfo::getIpInfoId));

        AppEhrResponse<List<LdapEhrEmpDto>> user = feignLdapService.getAllEmps();
        List<LdapEhrEmpDto> data1 = user.getData();
        Map<Integer, String> num2Oa = data1.stream().collect(Collectors.toMap(LdapEhrEmpDto::getOaUserId, LdapEhrEmpDto::getBadge));

        List<ReplenishmentInfo> toSaveList = new ArrayList<>();
        for(UploadReturnAmountDto item : readResList){
            ReplenishmentInfo toSave = new ReplenishmentInfo();
            String itUniqueKey = item.getItUniqueKey();
            if(StrUtil.isBlank(itUniqueKey)){
                logger.info("唯一标识为空");
                continue;
            }
            toSave.setItUniqueKey(itUniqueKey);
            String dataSource = judgeDataSource(itUniqueKey, allVirID,
                    allServerID, allIpinfoKey,key2INfoID,infoId2DetailList);
            //虚拟机
            if(itUniqueKey.startsWith("VD-")){
                toSave.setMachineStatus(virId2MarkStatus.get(itUniqueKey));
                String systemUserId = virId2UserId.get(itUniqueKey);
                if(StrUtil.isNotBlank(systemUserId)){
                    toSave.setSystemUserId(num2Oa.get(Integer.valueOf(systemUserId)));
                }
                toSave.setDataSource(dataSource);
                toSave.setSystemClassNo(virId2BusiNo.get(itUniqueKey));
                toSave.setVcIp(virId2IP1.get(itUniqueKey));
                toSaveList.add(toSave);
            }else{//物理机
                Integer idTemp = Integer.valueOf(itUniqueKey.trim());
                toSave.setMachineStatus(serId2DevieceStatus.get(idTemp));
                toSave.setMachineType(serId2DevieceType.get(idTemp));
                String systemUserId = serId2UserId.get(idTemp);
                if(StrUtil.isNotBlank(systemUserId)){
                    toSave.setSystemUserId(num2Oa.get(Integer.valueOf(systemUserId)));
                }
                toSave.setDataSource(dataSource);
                toSave.setSystemClassNo(serId2BusiNO.get(idTemp));
                toSave.setVcIp(serId2IP1.get(idTemp));
                toSaveList.add(toSave);
            }
        }
        replenishmentInfoRepo.deleteAll();
        replenishmentInfoRepo.saveAll(toSaveList);
        return context;
    }
    /**
     *
     * @param itUniqueKey
     * @param allVirID
     * @param allServerID
     * @param allIpinfoKey
     * @param key2INfoID
     * @param infoId2DetailList
     * @return
     */
    public String judgeDataSource(String itUniqueKey, Set<String> allVirID,
                                  Set<Integer> allServerID,Set<String> allIpinfoKey,
                                  Map<String, Long> key2INfoID,Map<Long, List<IpDetailInfo>> infoId2DetailList){
       if (itUniqueKey.startsWith("VD")) {
            if(!allVirID.contains(itUniqueKey)){
                return "IT资产没有的资产";
            }
        }else{
           if (!allServerID.contains(Integer.valueOf(itUniqueKey))) {
               return "IT资产没有的资产";
           }
        }
       if(!allIpinfoKey.contains(itUniqueKey)){
           return "IT资产有,成本分摊没有的资产";
       }
        List<IpDetailInfo> ipDetailInfoList = infoId2DetailList.get(key2INfoID.get(itUniqueKey));
        if (CollectionUtil.isEmpty(ipDetailInfoList)) {
            return "成本分摊有,但未填写分摊数据";
        }
        if (CollectionUtil.isNotEmpty(ipDetailInfoList)) {
            return "成本分摊有,并且有分摊数据";
        }
        return "无法判断数据来源";
    }

    public Page<ReplenishmentInfo> listpageReplenishment(ReplenishmentInfoQueryDto queryDto) {
        logger.info("开始查询数据分摊信息：{}", queryDto.toString());
        String pageSizeQuery = queryDto.getPageSize();
        String pageNoQuery = queryDto.getPageNo();
        Integer pageNo = Objects.nonNull(pageNoQuery) ? Integer.parseInt(pageNoQuery) : null;
        Integer pageSize = Objects.nonNull(pageSizeQuery) ? Integer.parseInt(pageSizeQuery) : null;
        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "id";
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);


        Map<String, Object> param = new HashMap<>();
        String queryDtoSystemClassNo = queryDto.getSystemClassNo();
        if(StrUtil.isNotEmpty(queryDtoSystemClassNo)){
            param.put("EQ_systemClassNo",queryDtoSystemClassNo);
        }

        String systemUserId = queryDto.getSystemUserId();
        if (StrUtil.isNotEmpty(systemUserId)) {
            param.put("EQ_systemUserId", systemUserId);
        }

        String ip = queryDto.getVcIp();
        if (StrUtil.isNotEmpty(ip)) {
            param.put("LIKE_vcIp", ip);
        }

        String dataSource = queryDto.getDataSource();
        if (StrUtil.isNotEmpty(dataSource)) {
            param.put("EQ_dataSource", dataSource);
        }

        String itUniqueKey = queryDto.getItUniqueKey();
        if (StrUtil.isNotEmpty(itUniqueKey)) {
            param.put("EQ_itUniqueKey", itUniqueKey);
        }
        String machineStatus = queryDto.getMachineStatus();
        if(StringUtils.isNotBlank(machineStatus)){
            param.put("EQ_machineStatus", machineStatus);
        }
        String machineType = queryDto.getMachineType();
        if(StringUtils.isNotBlank(machineType)){
            param.put("EQ_machineType", machineType);
        }
        List<ReplenishmentInfo> all = replenishmentInfoRepo.findAll(
                SpecificationUtil.buildSpecification(param, ReplenishmentInfo.class));
        if(CollectionUtil.isNotEmpty(all)){
            List<SystemMain> systemMainList = systemMainService.queryAll();
            Map<String,String> systemNameMap = systemMainList.stream()
                    .collect(Collectors.toMap(SystemMain::getSystemClassNo, SystemMain::getOpName));


            AppEhrResponse<List<LdapEhrEmpDto>> user = feignLdapService.getAllEmps();
            List<LdapEhrEmpDto> data1 = user.getData();
            Map<String, String> oa2Name = data1.stream()
                    .collect(Collectors.toMap(LdapEhrEmpDto::getBadge, LdapEhrEmpDto::getName));

            for (ReplenishmentInfo item : all) {
                String systemClassNo = item.getSystemClassNo();
                item.setSystemName(systemNameMap.getOrDefault(systemClassNo,systemClassNo));
                String systemUserId1 = item.getSystemUserId();
                item.setSystemUserName(oa2Name.getOrDefault(systemUserId1,systemUserId1));
            }
        }
        if(CollectionUtil.isEmpty(all)){
            return Page.empty();
        }
        return PageUtil.listConvertToPage(all, pageable);
    }
}
